﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using NASA.BeAMartian.TagGraph;
using System.Collections.ObjectModel;
using NASA.BeAMartian.TagGraph.Graph;
using NASA.BeAMartian.TagGraph.Surveying;
using NASA.BeAMartian.Controls;

namespace NASA.BeAMartian.Views.Participate
{
    public partial class Tags : UserControl
    {
        public event EventHandler<TagSelectedEventArgs> onTagSelected;
        public event EventHandler<EventArgs> TagsFormed;

        private Graphic _v;
        private NodeCollection<string> _nodes = new NodeCollection<string>();
        private event EventHandler<EventArgs> onLoadData;

        private object readingLock = new object();
        private Dictionary<string, Vertex> grp = new Dictionary<string, Vertex>();

        string RoverName;
        public ImageTagTypes TagType;

        public Tags()
        {
            InitializeComponent();
            this.SizeChanged += new SizeChangedEventHandler(Page_SizeChanged);
        }

        public void Load(string rover, ImageTagTypes tagType, List<ImageFeature> taggedFeatures)
        {            
            RoverName = rover;
            TagType = tagType;

            double h = Application.Current.Host.Content.ActualHeight;
            double w = Application.Current.Host.Content.ActualWidth;
            _v = new Graphic(new Size(1600, 500));
            _v.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            _v.onMouseEvent += new Graphic.MouseEvent(_v_onMouseEvent);
            _v.onMovingStoped += new EventHandler<EventArgs>(_v_onMovingStoped);
            _v.onTagSelected += new EventHandler<TagSelectedEventArgs>(_v_onTagSelected);

            _v.NodesBindingPath = "ChildNodes";
            _v.Nodes = new ObservableCollection<Node<string>>();

            InitData(taggedFeatures);

            // Add the result to the current screen //
            this.LayoutRoot.Children.Add(_v);

            UpdateCenterEdges(_nodes.Items[0]);
        }

        void _v_onTagSelected(object sender, TagSelectedEventArgs e)
        {
            if (onTagSelected != null) onTagSelected(this, e);
        }

        void Page_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (_v == null) return;
            double h = e.NewSize.Height;
            if (h <= 40) return;

            _v.Height = 500;
            _v.Width = 1600;
            _v.UpdateLayout();
        }

        void InitData(List<ImageFeature> taggedFeatures)
        {
            lock (readingLock)
            {
                ImageFeatures features = new ImageFeatures();
                features.RefreshTags(TagType.ToString(), RoverName);

                foreach (ImageFeature f in features)
                {
                    ImageFeature selection =
                        (from n in taggedFeatures
                         where n.Feature == f.Feature && n.TagType == f.TagType
                         select n).FirstOrDefault();

                    if(selection != null)
                        f.IsSelected = selection.IsSelected;
                }

                _nodes.AddNode(TagType.ToString());

                foreach (ImageFeature f in features)
                {
                    _nodes.AddNode(f.Feature);
                }

                grp[TagType.ToString()] = new Vertex() { Word = TagType.ToString(), Feature = new ImageFeature(TagType, "", "", TagType.ToString()) };

                foreach (ImageFeature f in features)
                {
                    grp[f.Feature] = new Vertex() { Word = f.Feature, Feature = new ImageFeature(TagType, f.Feature, f.Description, TagType.ToString()) { IsSelected = f.IsSelected } };
                }
                
                foreach (ImageFeature f in features)
                {
                    grp[TagType.ToString()].Neigh.Add(new Vertex() { Word = f.Feature, Feature = new ImageFeature(TagType, f.Feature, f.Description, TagType.ToString()) { IsSelected = f.IsSelected } });
                }

                _v.SetState(grp);
            }
        }

        public void ClearTags()
        {
            this.LayoutRoot.Children.Remove(_v);
        }

        void _v_onMovingStoped(object sender, EventArgs e)
        {
            if (TagsFormed != null) TagsFormed(this, e);
        }

        Random r = new Random();
        void _v_onMouseEvent(object sender, RoutedEventArgs e)
        {
            object obj = (sender as BeAMartian.TagGraph.Graph.Graphic.GraphContentPresenter).Content;
            Node<string> center = _nodes.GetNode((obj as Node<string>).Item);

            if (!"X||Sky||Rover||Land".Contains(obj.ToString()))
            {
                this.IsHitTestVisible = false;
            }

            UpdateCenterEdges(center.Item);
        }

        private void UpdateCenterEdges(string item)
        {
            int ItemsCount = (_nodes == null) ? 0 : _nodes.Items.Count;
            if (ItemsCount == 0) return;

            //if (CheckAccess())
            if (true)
            {
                Node<string> oldnode = _v.CenterObject as Node<String>;
                List<Node<String>> OldVertices = new List<Node<string>>();
                if (oldnode != null)
                {
                    OldVertices = _nodes.GetChildren(oldnode.Item);
#if OldVer
                    OldVertices.ForEach(el => _v.Nodes.Remove(el));
#endif
                }

                Node<string> node = _nodes.GetNode(item);
                _v.CenterObject = node;
                if (node != null)
                {
                    lock (readingLock)
                    {
                        List<Node<String>> Vertices = _nodes.GetChildren(node.Item);
                        Vertices.ForEach(el => _nodes.RemoveEdge(node.Item, el.Item));

                        List<Node<String>> LstNGD = new List<Node<string>>();

                        grp[node.Item].Neigh.ForEach(Vois =>
                        {
                            if (_nodes.Items.Contains(Vois.Word))
                            {
                                Node<string> newNode = _nodes.GetNode(Vois.Word);

                                if (!node.ChildNodes.Contains(newNode))
                                {
#if OldVer
                                    _nodes.AddEdge(node.Item, newNode.Item);
                                    _v.Nodes.Add(newNode);
#endif
                                    LstNGD.Add(newNode);
                                }
                            }
                        });
#if OldVer
#else
                        var newlist = LstNGD.Where(el => true).ToList();
                        OldVertices.ForEach(el =>
                        {
                            if (!LstNGD.Remove(el))
                                _v.Nodes.Remove(el);
                        });

                        newlist.ForEach(el =>
                        {
#if DEBUG1
                                Debug.Assert(!_nodes.ContainsEdge(node.Item, el.Item));
#endif
                            if (!_nodes.ContainsEdge(node.Item, el.Item))
                            {
                                _nodes.AddEdge(node.Item, el.Item);
                                if (LstNGD.Contains(el) && !_v.Nodes.Contains(el))
                                {
                                    _v.Nodes.Add(el);
                                }
                            }
                        });
#endif
                    }   //Lock_reading
                }
                if (onLoadData != null) onLoadData(node.Item, null);
            }
        }

        private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
        }        
    }
}
